package CI.aufgabe2.cip.mynodes;

import CI.aufgabe2.cip.SymbolTable;
import CI.aufgabe2.cip.base.AbstractDescr;
import CI.aufgabe2.cip.descriptor.ArrayDescr;
import CI.aufgabe2.cip.descriptor.RecordDescr;
import CI.aufgabe2.cip.descriptor.SimpleTypeDescr;

public class MyArraySelectorNode extends MyAbstractNode {
	private static final long serialVersionUID = 1L;

	public final MyAbstractNode subject;
	public final MyAbstractNode selector;

	public MyArraySelectorNode(MyAbstractNode subject, MyAbstractNode selector) {
		this.subject = subject;
		this.selector = selector;
	}

	@Override
	public void print() {
		trace("ArraySelectorNode");
		if (subject != null) {
			subject.print();
		}
		if (selector != null) {
			selector.print();
		}
		unindent();
	}

	public AbstractDescr compile(SymbolTable sym) {
		ArrayDescr value = null;

		if (subject instanceof MyIdNode) {
			// sym.declare(((MyIdNode)subject).strval, subject.compile(sym));
			value = (ArrayDescr) sym.getDescr(((MyIdNode) subject).strval);
			subject.compile(sym);
			selector.compile(sym);
			if (selector instanceof MyIdNode) {
				write("CONT, 1");
			}
			write("PUSHI, " + value.GetBasetype().getSize());
			write("MUL");
			write("ADD");
		} else {
			AbstractDescr abValue = subject.compile(sym);
			AbstractDescr reval = null;
			int size = 0;
			if (subject instanceof MyArraySelectorNode) {
				// Array
				selector.compile(sym);
				if (selector instanceof MyIdNode)
					write("CONT, 1");
				size = ((ArrayDescr) abValue).GetBasetype().getSize();
			} else if (subject instanceof MyRecordSelectorNode) {
				// Record
				
				if (selector instanceof MyIdNode) {
					size = ((RecordDescr)abValue).addressOf(((MyIdNode) selector).strval);
					reval = ((RecordDescr)abValue).getDesc(((MyIdNode) selector).strval);
				} else {
					size = ((MyIntNode) selector).intVal;
					reval = new SimpleTypeDescr("integer");
				}
			}
			// End
			write("PUSHI, " + size);
			write("MUL");
			write("ADD");
//			return reval;
			if (abValue instanceof ArrayDescr) {
				return abValue;
			} else if (abValue instanceof RecordDescr) {
				return reval;
			}
//
//			if (subject instanceof MyArraySelectorNode) {
//				value = (ArrayDescr) subject.compile(sym);
//				selector.compile(sym);
//				if (selector instanceof MyIdNode)
//					write("CONT, 1");
//				write("PUSHI, " + value.GetBasetype().getSize());
//				write("MUL");
//				write("ADD");
//			}
//			if (subject instanceof MyRecordSelectorNode) {
//				RecordDescr valueRec = (RecordDescr) subject.compile(sym);
//				int i = 0;
//				AbstractDescr reval = null;
//				if (selector instanceof MyIdNode) {
//					i = valueRec.addressOf(((MyIdNode) selector).strval);
//					reval = valueRec.getDesc(((MyIdNode) selector).strval);
//				} else {
//					i = ((MyIntNode) selector).intVal;
//					reval = new SimpleTypeDescr("integer");
//				}
//				write("PUSHI, " + i);
//				write("MUL");
//				write("ADD");
//				return reval;
//			}
		}
		return value;
	}
}
